<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<title>Cirodown editor demo</title>
<link rel="stylesheet" href="cirodown.min.css">
<style>
html, body {
  height: 100%;
  margin: 0;
  padding: 0;
  background-color: black;
}
#container {
  align-items: center;
  display: flex;
  /* https://stackoverflow.com/questions/12989931/body-height-100-displaying-vertical-scrollbar/46847795#46847795
   * 20 == 2x 10px padding (top + bottom). */
  height: calc(100% - 20px);
  padding: 10px;
}
#example {
  display: none;
}
#input {
  border: 1px black solid;
  flex-grow: 1;
  height: 100%;
  margin: 0 5px 0 0;
  overflow: hidden;
  width: 50%;
}
#output {
  border: 1px black solid;
  flex-grow: 1;
  height: 100%;
  margin: 0 0 0 5px;
  overflow: auto;
  width: 50%;
}
</style>
</head>
<body>
<div id="container">
<div id="input"></div>
<div id="output" class="cirodown"></div>
<div id="example">= Cirodown hello world

Welcome to Cirodown! Here's the table of contents:

\Toc

== Paragraphs, code, math

My first paragraph is amazing!

And the second one with inline code `f(){}` and inline server-side rendered maths with KaTeX: $\sqrt{1+1}$.

But if we want block code here it is:
``
f() {
  return 1;
}
``
and here is some block maths:
$$
\sqrt{1+1} \\
\sqrt{1+1}
$$

Ciro loves maths, and so equations can have titles, and references to math equations just work! See e.g.: \x[my-favorite-equation]
$$
\newcommand{\va}[1]{\overrightarrow{#1}}
\newcommand{\B}[0]{\va{\mathbf{B}}}
\newcommand{\E}[0]{\va{\mathbf{E}}}
\newcommand{\divergence}[1]{\nabla \cdot #1}
\newcommand{\vacuumPermittivity}[0]{\varepsilon_0}
\divergence{\E} = \frac{\rho}{\vacuumPermittivity} \\
\divergence{\B} = 0
$$
{title=This is my favorite equation in the entire world!!!}
{id=my-favorite-equation}

We try to make anything escapable with a backslash, e.g.:
* literal backslash \\notmacro
* code and math: \` and \$

If you want more than three backticks in your insane code block, you can add more to the open:
````
Here  are three backticks:
```
Nice!
````
or you can also use the equivalent sane literals:
\C[[
Here  are three backticks:
```
Nice!
]]

== Lists, tables, quotations

Meh, the usual. Insane list:
* first item
* second item
  * some nesting
  * and some more
* third item
Sane list with explicit `Ul`:
\Ul[
\L[first item]
\L[second item]
]

And now for tables, see this one \x[table-my-table].
\Table
{title=My table title}
{id=table-my-table}
[
|| Header 1
|| Header 2

| 1 1
| 1 2

| 2 1
| 2 2

| 3 1

  A paragraph!
| 3 2
]

And a quotation:
\Q[To be or not to be!

Cirodown is the answer.]

== References, headers, images

Ciro loves headers and headers!

Reference to a header: \x[paragraphs-code-math]. Or if you want to show the section id: \x[paragraphs-code-math]{style=full}.

Reference to the following image: \x[image-my-xi-chrysanthemum].

\Image[https://raw.githubusercontent.com/cirosantilli/media/master/Chrysanthemum_Xi_Jinping_with_black_red_liusi_added_by_Ciro_Santilli.jpg]
{title=Xi Chrysanthemum is a very nice image}
{id=image-my-xi-chrysanthemum}
{source=https://commons.wikimedia.org/wiki/File:Lotus_flower_(978659).jpg}

Reference to a fixed-uppercase header: \x[ciro-is-awesome].

Force non-fixed case header to be uppercase and plural: \x[dog]{c}{p}.

=== Ciro is awesome
{c}

=== Dog

=== Unlimited header levels?!

==== My h4

===== My h5

====== My h6

\H[7][My h7]

\H[8][My h8]

\H[9][My h9]

\H[10][My h10]

\H[11][My h11]

\H[12][My h12]

\H[13][My h13]

= Parent determined by ID!!!
{parent=my-h9}

You don't need to worry about counting header anymore!

== Mostly testing now I confess

Literal named argument:
``
my nice code
``
{{title=Nice code}}
</div>
</div>
<script src="cirodown.js"></script>
<script>
// Otherwise the monaco-editor loader messes up with browserify and cirodown is not visible...
const my_cirodown = cirodown;
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/loader.min.js"></script>
<script>
const example_elem = document.getElementById('example');
const input_elem = document.getElementById('input');
const output_elem = document.getElementById('output');

require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs' }});
window.MonacoEnvironment = { getWorkerUrl: () => proxy };
const proxy = URL.createObjectURL(new Blob([`
  self.MonacoEnvironment = {
    baseUrl: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min'
  };
  importScripts('https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/base/worker/workerMain.min.js');
`], { type: 'text/javascript' }));
require(["vs/editor/editor.main"], function () {
  monaco.languages.register({
    id: 'cirodown'
  });
  // TODO replace with our own tokenizer output:
  // https://github.com/cirosantilli/cirodown/issues/106
  monaco.languages.setMonarchTokensProvider('cirodown', {
    macroName: /[a-zA-Z0-9_]+/,
    tokenizer: {
      root: [
        [/\\@macroName/, 'macro'],
        [/\\./, 'escape'],

        // Positional arguments.
        [/\[\[\[/, 'literalStart', 'argumentDelimLiteral2'],
        [/\[\[/, 'literalStart', 'argumentDelimLiteral'],
        [/[[\]}]/, 'argumentDelim'],

        // Named arguments.
        [/{{/, 'argumentDelim', 'argumentNameLiteral'],
        [/{/, 'argumentDelim', 'argumentName'],

        [/\$\$\$/, 'literalStart', 'insaneMath3'],
        [/\$\$/, 'literalStart', 'insaneMath2'],
        [/\$/, 'literalStart', 'insaneMath'],

        [/````/, 'literalStart', 'insaneCode4'],
        [/```/, 'literalStart', 'insaneCode3'],
        [/``/, 'literalStart', 'insaneCode2'],
        [/`/, 'literalStart', 'insaneCode'],

        [/^=+ .*/, 'insaneHeader'],

        // Insane list.
        [/^(  )*\*( |$)/, 'argumentDelim'],
        // Insane table.
        [/^(  )*\|\|( |$)/, 'argumentDelim'],
        [/^(  )*\|( |$)/, 'argumentDelim'],
      ],
      argumentDelimLiteral: [
        [/\]\]/, 'literalStart', '@pop'],
        [/./, 'literalInside'],
      ],
      argumentDelimLiteral2: [
        [/\]\]\]/, 'literalStart', '@pop'],
        [/./, 'literalInside'],
      ],
      argumentName: [
        [/@macroName/, 'argumentName'],
        [/=/, 'argumentDelim', '@pop'],
        [/}/, 'argumentDelim', '@pop'],
      ],
      // TODO find a way to make content literalInside.
      argumentNameLiteral: [
        [/@macroName/, 'argumentName'],
        [/=/, 'argumentDelim', '@pop'],
        [/}}/, 'argumentDelim', '@pop'],
      ],
      insaneCode: [
        [/`/, 'literalStart', '@pop'],
        [/./, 'literalInside'],
      ],
      insaneCode2: [
        [/``/, 'literalStart', '@pop'],
        [/./, 'literalInside'],
      ],
      insaneCode3: [
        [/```/, 'literalStart', '@pop'],
        [/./, 'literalInside'],
      ],
      insaneCode4: [
        [/````/, 'literalStart', '@pop'],
        [/./, 'literalInside'],
      ],
      insaneMath: [
        [/\$/, 'literalStart', '@pop'],
        [/./, 'literalInside'],
      ],
      insaneMath2: [
        [/\$\$/, 'literalStart', '@pop'],
        [/./, 'literalInside'],
      ],
      insaneMath3: [
        [/\$\$\$/, 'literalStart', '@pop'],
        [/./, 'literalInside'],
      ],
     }
  });
  monaco.editor.defineTheme('vs-dark-cirodown', {
    base: 'vs-dark',
    inherit: true,
    rules: [
      { token: 'argumentDelim', foreground: 'FFFFFF', fontStyle: 'bold' },
      { token: 'argumentName', foreground: 'FFAAFF', fontStyle: 'bold'},
      { token: 'insaneHeader', foreground: 'FFFF00', fontStyle: 'bold' },
      { token: 'literalStart', foreground: 'FFFF00', fontStyle: 'bold' },
      { token: 'literalInside', foreground: 'FFFF88' },
      { token: 'macro', foreground: 'FF8800', fontStyle: 'bold' },
    ]
  });
  const editor = monaco.editor.create(
    input_elem,
    {
      // https://stackoverflow.com/questions/47017753/monaco-editor-dynamically-resizable
      automaticLayout: true,
      folding: false,
      language: 'cirodown',
      minimap: {enabled: false},
      scrollBeyondLastLine: false,
      theme: 'vs-dark-cirodown',
      wordWrap: 'on',
      value: example_elem.textContent,
    }
  );
  editor.onDidChangeModelContent(function (e) {
    convert_input();
  });
  editor.onDidScrollChange(function (e) {
    const range = editor.getVisibleRanges()[0];
    scroll_preview_to_source_line(range.startLineNumber, 'start');
  });
  editor.onDidChangeCursorPosition(function (e) {
    scroll_preview_to_source_line(e.position.lineNumber, 'center');
  });
  let line_to_id;
  function convert_input() {
    let extra_returns = {};
    output_elem.innerHTML = my_cirodown.convert(
      editor.getValue(),
      {'body_only': true},
      extra_returns
    );
    line_to_id = extra_returns.context.line_to_id;
  }
  function scroll_preview_to_source_line(line_number, block) {
    if (block === undefined) {
      block = 'center';
    }
    const id = line_to_id(line_number);
    if (
      // Possible on empty document.
      id !== undefined
    ) {
      // TODO this would be awesome to make the element being targeted red,
      // but it loses editor focus  on new paragraphs (e.g. double newline,
      // making it unusable.
      // window.location.hash = id;
      document.getElementById(id).scrollIntoView({
        behavior: 'smooth',
        block: block,
      });
    };
  }
  convert_input();
});
</script>
<!-- TODO this duplicates with code in ./cirodown but I'm lazy to solve it better right now -->
<script src="node_modules/tablesort/src/tablesort.js"></script>
<script src="node_modules/tablesort/src/sorts/tablesort.date.js"></script>
<script src="node_modules/tablesort/src/sorts/tablesort.dotsep.js"></script>
<script src="node_modules/tablesort/src/sorts/tablesort.filesize.js"></script>
<script src="node_modules/tablesort/src/sorts/tablesort.monthname.js"></script>
<script src="node_modules/tablesort/src/sorts/tablesort.number.js"></script>

<script src="cirodown.runtime.js"></script>
</body>
</html>
